home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
djgpp
/
utils
/
djtarx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-27
|
8KB
|
356 lines
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <dos.h>
#include <time.h>
#include <io.h>
#include "oread.h"
void Fatal(char *msg)
{
fprintf(stderr, "Fatal! %s!\n", msg);
exit(1);
}
/*------------------------------------------------------------------------*/
typedef struct CE {
struct CE *next;
char *from;
char *to;
} CE;
#define HASHSIZE 2048
#define HASHMASK 2047
#define HASHBITS 11
CE *htab[HASHSIZE];
unsigned long hash(unsigned char *cp)
{
unsigned long rv = 0;
while (*cp)
rv += *cp++;
while (rv > HASHMASK)
rv = (rv & HASHMASK) + (rv >> HASHBITS);
return rv;
}
void store_entry(char *from, char *to)
{
unsigned long h = hash(from);
CE *ce = (CE *)malloc(sizeof(CE));
if (ce == 0)
Fatal("Out of memory");
ce->from = strdup(from);
ce->to = strdup(to);
ce->next = htab[h];
htab[h] = ce;
}
char *get_entry(char *from)
{
CE *ce;
for (ce = htab[hash(from)]; ce; ce=ce->next)
{
if (strcmp(ce->from, from) == 0)
return ce->to;
}
return from;
}
void DoNameChanges(char *fname)
{
FILE *f = fopen(fname, "r");
char from[100], to[100];
char line[250];
if (f == 0)
{
perror(fname);
exit(1);
}
while (1)
{
fgets(line, 250, f);
if (feof(f))
break;
to[0] = 0;
sscanf(line, "%s %s", from, to);
if (to[0])
store_entry(from, to);
}
fclose(f);
}
/*------------------------------------------------------------------------*/
FILE *change_file;
int v_switch = 0;
main(int argc, char **argv)
{
int i = 1;
if (argc < 2)
{
fprintf(stderr, "djtarx [-n changeFile] [-v] tarfile . . .\n");
exit(1);
}
while ((argc > i) && (argv[i][0] == '-'))
{
switch (argv[i][1])
{
case 'n':
DoNameChanges(argv[i+1]);
i++;
break;
case 'v':
v_switch = 1;
break;
}
i++;
}
for (; i < argc; i++)
tarread(argv[i]);
change_file = fopen("/tarchange.lst", "w");
dump_changes();
fclose(change_file);
}
/*------------------------------------------------------------------------*/
typedef struct CHANGE {
struct CHANGE *next;
char *old;
char *new;
int isdir; /* 0=file, 1=dir, 2=skip */
} CHANGE;
CHANGE *change_root = 0;
dump_changes()
{
CHANGE *c;
for (c=change_root; c; c=c->next)
fprintf(change_file, "%s -> %s\n", c->old, c->new);
}
int change(char *fname, char *problem, int isadir)
{
CHANGE *ch;
char new[200];
char *pos, *info;
for (ch=change_root; ch; ch = ch->next)
if ((strncmp(fname, ch->old, strlen(ch->old)) == 0) && ch->isdir)
{
if (ch->isdir == 2)
{
printf(" [ skipping %s ]\n", fname);
return 0;
}
/* printf(" [ changing %s to ", fname); */
sprintf(new, "%s%s", ch->new, fname+strlen(ch->old));
strcpy(fname, new);
/* printf("%s ]\n", fname); */
return 1;
}
info = strstr(fname, ".info-");
if (info)
{
strcpy(new, fname);
info = strstr(new, ".info-");
strcpy(info+2, info+6);
printf("[ changing %s to %s ]\n", fname, new);
}
else
{
char *plus = strstr(fname, "++"), *plus2;
if (plus)
{
strcpy(new, fname);
plus2 = strstr(new, "++");
strcpy(plus2, "plus");
strcpy(plus2+4, plus+2);
}
else
{
printf(" %s %s\n new name : ", problem, fname);
gets(new);
}
}
if ((strcmp(new, "") == 0) && (isadir == 2))
return 0;
if (isadir) isadir=1;
ch = (CHANGE *)malloc(sizeof(CHANGE));
if (ch == 0)
Fatal("Out of memory");
ch->next = change_root;
change_root = ch;
ch->old = strdup(fname);
pos = strrchr(fname, '/');
if (pos && (strchr(new, '/') == 0))
{
ch->new = (char *)malloc(strlen(new) + (pos-fname) + 2);
if (ch->new == 0)
Fatal("Out of memory");
*pos = 0;
sprintf(ch->new, "%s/%s", fname, new);
}
else
ch->new = strdup(new);
ch->isdir = isadir;
strcpy(fname, ch->new);
if (new[0] == 0)
{
ch->isdir = 2;
return 0;
}
return 1;
}
/*------------------------------------------------------------------------*/
void
do_directories(char *n)
{
char *sl;
for (sl=n; *sl; sl++)
{
if (*sl == '/' || *sl == '\\')
{
char save = *sl;
*sl = 0;
mkdir (n);
*sl = save;
}
}
}
/*------------------------------------------------------------------------*/
typedef struct {
char name[100];
char operm[8];
char ouid[8];
char ogid[8];
char osize[11];
char otime[12];
char ocsum[8];
char flags[1];
char filler[356];
} TARREC;
char buf[512];
tarread(char *fname)
{
TARREC header;
int r;
void *f;
long perm, uid, gid, size, ftime, csum;
int dsize;
char *changed_name;
long posn=0;
struct tm tm;
f = oread_open(fname);
while (1)
{
oread_read(f, &header);
if (header.name[0] == 0)
break;
sscanf(header.operm, "%lo", &perm);
sscanf(header.ouid, "%lo", &uid);
sscanf(header.ogid, "%lo", &gid);
sscanf(header.osize, "%lo", &size);
sscanf(header.otime, "%lo", &ftime);
changed_name = get_entry(header.name);
if (v_switch)
printf("%08lx %6lo ", posn, perm);
else
printf("%c%c%c%c ",
perm & 040000 ? 'd' : '-',
perm & 000400 ? 'r' : '-',
perm & 000200 ? 'w' : '-',
perm & 000100 ? 'x' : '-');
printf("%.20s %9ld %s", ctime(&ftime)+4, size, changed_name);
if (header.flags[1] == 0x32)
printf(" -> %s", header.filler);
printf("\n");
posn += 512 + (size+511) & ~511;
/* printf("%6lo %02x %12ld %s\n", perm, header.flags[0], size, changed_name); */
if (changed_name[strlen(changed_name)-1] == '/')
{
changed_name[strlen(changed_name)-1] = 0;
do {
r = mkdir(changed_name
#ifdef __GO32__
,0
#endif
);
if (r && (errno==EACCES))
{
change(changed_name, "Duplicate directory name", 2);
continue;
}
if (r)
r = change(changed_name, "Unable to create directory", 1);
else
printf("Making directory %s\n", changed_name);
} while (r);
}
else
{
open_file:
do_directories(changed_name);
r = open(changed_name, O_WRONLY|O_BINARY|O_CREAT|O_EXCL,
S_IWRITE|S_IREAD);
if (r < 0)
if (change(changed_name, "Cannot exclusively open file", 0))
goto open_file;
else
{
oread_skip(f, (size+511) & ~511);
}
else
{
long ftv;
struct ftime ftimes;
struct tm *tm;
while (size)
{
if (size < 512)
dsize = size;
else
dsize = 512;
oread_read(f, buf);
if (write(r, buf, dsize) < dsize)
{
printf("Out of disk space\n");
exit(1);
}
size -= dsize;
}
close(r);
r = open(changed_name, O_RDONLY);
tm = localtime(&ftime);
ftimes.ft_tsec = tm->tm_sec / 2;
ftimes.ft_min = tm->tm_min;
ftimes.ft_hour = tm->tm_hour;
ftimes.ft_day = tm->tm_mday;
ftimes.ft_month = tm->tm_mon+1;
ftimes.ft_year = tm->tm_year - 80;
setftime(r, &ftimes);
close(r);
if (!(perm & 0200))
_chmod(changed_name, 1, FA_RDONLY);
}
}
}
oread_close(f);
}